var uuid        = require('node-uuid'),
    helper      = require('../utils/helper'),
    dateformat  = require('dateformat');

function DaoMysql(cfg, pool, log, cache) {
    if (!cfg || !pool || !log) {
        throw new Error("Config and connection vars,  and log function are required.");
    }
    this.config = cfg;
    this.pool = pool;
    this.log = log;
    this.cache = cache;
}

DaoMysql.prototype.registerModel = function(itemClass) {
    // Don't need this here, but keeping for compataibility with my other DAOs.
    return;
};

DaoMysql.prototype.create = function(item, callback) {
    var that = this;
    var created = dateformat('yyyy-mm-dd HH:MM:ss');
    var item_id = uuid();
    item_id = item_id.replace(/-/g, "");
    if (item) {
        item[ item.getEntityIndex() ] = item_id;
        item[ item.getEntityCreated() ] = created;
        var itemAsArray = item.asArray();
        var valuesForQuery = '?' + Array(itemAsArray.length).join(',?');
        var queryStr = 'INSERT INTO ' + this.config.dbname + '.' + item.getEntityName() + ' VALUES(' + valuesForQuery + ')';
        this.log('create(): ' + queryStr);
        that.pool.acquire(function(err, client) {
        	client.query(queryStr, itemAsArray, function(err) {
                if (err) {
                    that.log('Error: create(): ' + err);
                } else if (that.cache) {
                    that.cache.putItem(item);                   // cache item
                    that.cache.delItems(item.getClass());       // clear all items cache
                }
                if (callback) {
                    callback(err, item);
                }
                that.pool.release(client);
                return item;
            });	
       });
    } else {
        this.log('Error: create(): cannot save item');
        if (callback) {
            callback(true, null);
        }
        return null;
    }
};

DaoMysql.prototype.update = function(item, callback) {
    var that = this;
    var updated = dateformat('yyyy-mm-dd HH:MM:ss');
    if (item) {
        item[ item.getEntityCreated() ] = updated;
        // we assume first element in props is an index
        var propNames = item.getPropNamesAsArray();
        var slicedFields = propNames.slice(-propNames.length+1);
        var fieldsStr = slicedFields.join(' = ?, ') + ' = ?';
        var asArray = item.asArray();
        var itemAsArrayWithMovedIndex = asArray.splice(-asArray.length+1);
        itemAsArrayWithMovedIndex.push(asArray[0]);
        var queryStr = 'UPDATE ' + this.config.dbname + '.' + item.getEntityName() + ' SET ' + fieldsStr + ' WHERE ' + item.getEntityIndex() + ' = ?';
        this.log('update(): ' + queryStr);
        that.pool.acquire(function(err, client) {
        	client.query(queryStr, itemAsArrayWithMovedIndex, function(err) {
                if (err) {
                    that.log('Error: update(): ' + err);
                } else if (that.cache) {
                    that.cache.putItem(item);               
                    that.cache.delItems(item.getClass());
                }
                if (callback) {
                    callback(err, item);
                }
                that.pool.release(client);
                return item;
            });
       });
    } else {
        this.log('Error: update(): cannot update item');
        if (callback) {
            callback(true, null);
        }
        return null;
    }
};

DaoMysql.prototype.list = function(itemClass, propNames, callback) {
    var that = this;
    if (this.cache) {
        this.cache.getItems(itemClass, function(cachedErr, cachedResult) {   // get from cache
            if (cachedErr || !cachedResult) {
                var fields = propNames ? propNames : itemClass.propNamesAsArray;
                var queryStr = 'SELECT ' + fields.join(',') + ' FROM ' + that.config.dbname + '.' + itemClass.entityName + ' ORDER BY ' + itemClass.entityIndex + ' DESC';
                that.log('list(): ' + queryStr);
                that.pool.acquire(function(err, client) {
                	client.query(queryStr, function(err, results, fields) {
                        if (err) {
                            that.log('Error: list(): ' + err);
                        } else if (that.cache) {
                            that.cache.putItems(itemClass, results);            // cache all items
                        }
                        if (callback) {
                            callback(err, results);
                        }
                        that.pool.release(client);
                        return results;
                    });
                });
            } else {
                if (callback) {
                    callback(false, cachedResult);
                }
                return cachedResult; 
            }
        });
    }
};

DaoMysql.prototype.get = function(itemClass, itemId, callback) {
    var that = this;
    if (this.cache) {
        this.cache.getItem(itemClass, itemId, function(cachedErr, cachedResult) {   // get from cache
            if (cachedErr || !cachedResult) {
                var queryStr = 'SELECT ' + itemClass.propNamesAsArray.join(',') + ' FROM ' + that.config.dbname + '.' + itemClass.entityName + ' WHERE ' + itemClass.entityIndex + ' = ? LIMIT 1';
                that.log('get(): ' + queryStr);
                that.pool.acquire(function(err, client) {
                	client.query(queryStr, [ itemId ], function(err, result, fields) {
	                    var itemResult = result ? result[0] : null;
	                    if (err) {
	                        that.log('Error: get(): ' + err);
	                    } else if (that.cache) {
	                        that.cache.putItemByClass(itemClass, itemResult);     // put to cache
	                    }
	                    if (callback) {
	                        callback(err, itemResult);
	                    }
	                    that.pool.release(client);
	                    return itemResult;
	                });
                });
            } else {
                if (callback) {
                    callback(false, cachedResult);
                }
                return cachedResult;
            }
        });
    }
};

DaoMysql.prototype.search = function(itemClass, where, callback) {
    var that = this;
    var key	 = where;
    if (this.cache) {
        this.cache.search(itemClass,key,function(cachedErr, cachedResult) {   // get from cache
            if (cachedErr || !cachedResult) {
            	dbsearch(itemClass,key,that,where,null,null,callback);
            } else {
                if (callback) {
                    callback(false,cachedResult,cachedResult.length);
                }
                return cachedResult;
            }
        });
    }else{
    	dbsearch(itemClass,key,that,where,null,null,callback);
    }
};

function dbsearch(itemClass,key,that,where,limit,totalcount,callback){
	var queryStr = 'SELECT ' + itemClass.propNamesAsArray.join(',') + ' FROM ' + that.config.dbname + '.' + itemClass.entityName;
    if(where){
    	queryStr+= " WHERE "+where;
    }
    if(limit){
    	var ls=limit.split(',');
    	if(ls.length>1){
    		var start=parseInt(ls[0])*parseInt(ls[1]);
    		var end=parseInt(ls[1]);
    		queryStr+= " limit "+start+","+end;
    	}else{
    		queryStr+= " limit "+limit;
    	}
    }
    that.log('search(): ' + queryStr);
    that.pool.acquire(function(err, client) {
    	client.query(queryStr, function(err, results, fields) {
	        if (err) {
	            that.log('Error: search(): ' + err);
	        } else if (that.cache) {
	            that.cache.putSearch(itemClass,key,results);            // cache all items
	        }
	        if (callback) {
	        	if(totalcount){
	        		callback(err,results,totalcount);
	        	}else{
	        		if(results){
	        			callback(err,results,results.length);
	        		}else{
	        			callback(err,results,0);
	        		}
	        	}
	        }
	        that.pool.release(client);
	        return results;
	    });
    });
}


DaoMysql.prototype.searchPage = function(itemClass, where,limit, callback) {
    var that = this;
    var key =where+limit;
	var countKey="[[[count]]]"+where;
    if (this.cache) {
    	this.cache.search(itemClass,countKey,function(cachedErr, cachedResult) {
    		 if (cachedErr || !cachedResult || cachedResult.length<1) {
    			 dbSearchCount(itemClass,key,countKey,that,where,limit,callback);
    		 }else{
    			 var total=cachedResult[0].totalcount1234;
    			 that.cache.search(itemClass,key,function(cachedErr, cachedResult) {   // get from cache
			            if (cachedErr || !cachedResult) {
			            	dbsearch(itemClass,key,that,where,limit,total,callback);
			            } else {
			                if (callback) {
			                    callback(false,cachedResult,total);
			                }
			                return cachedResult;
			            }
			      });
    		 }
    	 });
    }else{
    	dbSearchCount(itemClass,key,countKey,that,where,limit,callback);
    }
};

//获得数量
function dbSearchCount(itemClass,key,countKey,that,where,limit,callback){
	var queryStr = 'SELECT COUNT(*) as totalcount1234  FROM ' + that.config.dbname + '.' + itemClass.entityName;
    if(where){
    	queryStr+= " WHERE "+where;
    }
    that.log('dbSearchCount(): ' + queryStr);
    that.pool.acquire(function(err, client) {
    	client.query(queryStr, function(err, results, fields) {
	        if (err || !results || results.length<1) {
	            that.log('Error: search(): ' + err);
	        } else if (that.cache) {
	            that.cache.putSearch(itemClass,countKey,results);            // cache all items
	        }
	        var r=results[0].totalcount1234;
	        that.cache.search(itemClass,key,function(cachedErr, cachedResult) {   // get from cache
	            if (cachedErr || !cachedResult) {
	            	 dbsearch(itemClass,key,that,where,limit,r,callback);
	            } else {
	                if (callback) {
	                    callback(false,cachedResult,r);
	                }
	                return cachedResult;
	            }
	      });
	       that.pool.release(client);
	       return results;
	    });
    });
}


//删除
DaoMysql.prototype.remove = function(itemClass, itemId, callback) {
    var that = this;
    var queryStr = 'DELETE FROM ' + this.config.dbname + '.' + itemClass.entityName + ' WHERE ' + itemClass.entityIndex + ' = ?';
    this.log('remove(): ' + queryStr);
    that.pool.acquire(function(err, client) {
    	client.query(queryStr, [ itemId ], function(err, result, fields) {
	        if (err) {
	            that.log('Error: remove(): ' + err);
	        } else if (that.cache) {
	            that.cache.delItem(itemClass, itemId);      // del item from cache
	            that.cache.delItems(itemClass);             // clear all items cache
	        }
	        if (callback) {
	            callback(err, null);
	        }
	        that.pool.release(client);
	        return null;
	    });
    });
};


module.exports.DaoMysql = DaoMysql;